from gmssl import sm3, func
import json
from ..common.enums import algo_types
from . import sign_util, sm4_util
from app import conf
from app.models.account import SubAccount

import logging

logger = logging.getLogger(__name__)

class BzPayUtil():
    "报文签名加密工具"

    algo = ''
    data = {}
    secret_key: str = conf.SECRET_KEY
    pri_key = conf.SM_PRI_KEY
    pub_key = conf.SM_PUB_KEY

    def __init__(self, secret_key='', pri_key='', pub_key=''):
        #self.data = data
        if secret_key:
            self.secret_key = secret_key
        if pri_key:
            self.pri_key = pri_key
        if pub_key:
            self.pub_key = pub_key

    def genEncParam(data):
        pass

    @staticmethod
    def sign_balance(acc: SubAccount):
        salt_msg = f'{acc.primary_acc_no}.{acc.sub_type}.{acc.balance}'
        bytes_list = func.bytes_to_list(salt_msg.encode('utf-8'))
        hashed = sm3.sm3_hash(bytes_list)
        #print('hash: ', hashed)
        return hashed
        
    @staticmethod
    def verify_balance(acc: SubAccount):
        #msg = str(amount).encode('utf-8')
        salt_msg = f'{acc.primary_acc_no}.{acc.sub_type}.{acc.balance}'
        bytes_list = func.bytes_to_list(salt_msg.encode('utf-8'))
        new_hashed = sm3.sm3_hash(bytes_list)
        #print('hash: ', new_hashed)
        return acc.balance_sign == new_hashed
    
    def sign_with_sm2(self, data):
        kvstr = self.gen_kvstr(data)
        sm_sign = sign_util.SM3WithSM2Util.sign(kvstr, self.pri_key, self.pub_key)
        return sm_sign 
    
    def sign_str_with_sm2(self, kvstr):
        sm_sign = sign_util.SM3WithSM2Util.sign(kvstr, self.pri_key, self.pub_key)
        return sm_sign 
    
    def verify_with_sm2(self, data, signature):
        kvstr = self.gen_kvstr(data)
        sm_sign = sign_util.SM3WithSM2Util.verify(kvstr, signature, self.pub_key)
        return sm_sign 
    
    def verify_str_with_sm2(self, kvstr, signature):
        sm_sign = sign_util.SM3WithSM2Util.verify(kvstr, signature, self.pub_key)
        return sm_sign 
    
    def encrypt_with_sm4(self, data):
        #kvstr = self.gen_kvstr(data)
        enc_hex = sm4_util.encrypt_ecb_to_hex(json.dumps(data), self.secret_key)
        return enc_hex
    
    def decrypt_with_sm4(self, enc_hex: str):
        json_str = sm4_util.decrypt_ecb_from_hex(enc_hex, self.secret_key)
        return json.loads(json_str)
        #return self.gen_dict(kvstr)
    
    def encrypt_with_sm4_bak(self, data):
        kvstr = self.gen_kvstr(data)
        enc_hex = sm4_util.encrypt_ecb_to_hex(kvstr, self.secret_key)
        return enc_hex
    
    def encrypt_str_with_sm4(self, data: str):
        enc_hex = sm4_util.encrypt_ecb_to_hex(data, self.secret_key)
        return enc_hex
    
    def decrypt_with_sm4_to_kvstr(self, enc_hex: str):
        kvstr = sm4_util.decrypt_ecb_from_hex(enc_hex, self.secret_key)
        return kvstr
    
    def sign_merc_payload_with_rsa(self):
        kvstr = self.gen_kvstr()
        rsa_sign = sign_util.SHA256WithRSAUtil.signature(kvstr, self.pri_key)
        return rsa_sign

    def gen_kvstr(self, data):
        '''
        生成 key1=value2&key2=value2 格式字符串
        '''
        kvstr = ''
        for k in sorted(data):
            kvstr += k + '=' + str(data[k]) + '&'
        kvstr = kvstr[:-1]
        return kvstr
    
    def gen_dict(self, kvstr: str):
        '''
        将kv字符串 (key1=value2&key2=value2) 转化为字典
        '''
        data = {}
        try:
            kv_list = kvstr.split('&')
            for it in kv_list:
                kv = it.split('=')
                data[kv[0]] = kv[1]
            return data
        except Exception as err:
            logger.error(err)
            raise Exception('生成参数字典失败')
        

